package online.flowerinsnow.minecraft.bukkit.testffa.listener;

import online.flowerinsnow.minecraft.bukkit.testffa.Main;
import online.flowerinsnow.minecraft.bukkit.testffa.core.TestFFACore;
import online.flowerinsnow.minecraft.bukkit.testffa.event.PlayerDiedEvent;
import online.flowerinsnow.minecraft.bukkit.testffa.gui.KitEditGUI;
import online.flowerinsnow.minecraft.bukkit.testffa.manager.KitManager;
import online.flowerinsnow.minecraft.bukkit.testffa.manager.PlayerKitManager;
import online.flowerinsnow.minecraft.bukkit.testffa.manager.ScoreboardManager;
import online.flowerinsnow.minecraft.bukkit.testffa.runnable.FakeGlassRunnable;
import online.flowerinsnow.minecraft.bukkit.testffa.stats.PlayerStatsImpl;
import online.flowerinsnow.minecraft.bukkit.testffa.util.ColorUtils;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.entity.Projectile;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.Action;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.event.entity.EntityRegainHealthEvent;
import org.bukkit.event.entity.FoodLevelChangeEvent;
import org.bukkit.event.player.*;
import org.bukkit.scoreboard.Objective;
import org.bukkit.scoreboard.Scoreboard;
import org.bukkit.util.Vector;

public class PlayerProtectionListener implements Listener {
    @EventHandler
    public void onDamage(EntityDamageEvent e) {
        if (!(e.getEntity() instanceof Player)) return; // 受击的实体不是玩家 不管它
        Location loc = e.getEntity().getLocation(); // 获取玩家位置
        if (loc.getX() < 16 && loc.getX() > -16 && loc.getZ() < 16 && loc.getZ() > -16) { // 玩家在出生点
            e.setCancelled(true);
            return;
        }
        Player player = (Player) e.getEntity();
        if (e instanceof EntityDamageByEntityEvent) { // 如果说是被其它生物所伤害
            EntityDamageByEntityEvent event = (EntityDamageByEntityEvent) e;
            Entity dmgr = event.getDamager();
            if (dmgr instanceof Projectile) { // 造成伤害的是弹射物 实则造成伤害的是弹射物的发射者
                dmgr = (Entity) ((Projectile) dmgr).getShooter();
                if (dmgr == null) return;
            }
            if (!(event.getDamager() instanceof Player)) {
                return;
            }
            Player damager = (Player) dmgr;
            TestFFACore.getCombatManager().setCombatTime(player, 30);
            TestFFACore.getCombatManager().setCombatTarget(player, damager);
            TestFFACore.getCombatManager().setCombatTime(damager, 30);
            TestFFACore.getCombatManager().setCombatTarget(damager, player);
        }

        if (e.getFinalDamage() > player.getHealth()) {
            PlayerDiedEvent evt = new PlayerDiedEvent(player, TestFFACore.getCombatManager().getCombatTarget(player));
            Bukkit.getPluginManager().callEvent(evt);
            if (evt.isCancelled()) e.setCancelled(true);
            else {
                e.setDamage(0);
                player.getActivePotionEffects().forEach(p -> player.removePotionEffect(p.getType()));
            }
        }
    }

    @EventHandler
    public void onHunger(FoodLevelChangeEvent e) {
        if (!(e.getEntity() instanceof Player)) return;
        Location loc = e.getEntity().getLocation(); // 获取玩家位置
        if (loc.getX() < 16 && loc.getX() > -16 && loc.getZ() < 16 && loc.getZ() > -16) { // 玩家在出生点
            e.setFoodLevel(20);
        }
    }

    @EventHandler
    public void moveSpawn(PlayerMoveEvent e) { // 玩家回到出生点
        Location loc = e.getPlayer().getLocation(); // 获取玩家位置
        if (loc.getX() < 16 && loc.getX() > -16 && loc.getZ() < 16 && loc.getZ() > -16) { // 玩家在出生点
            e.getPlayer().setFoodLevel(20);
            e.getPlayer().setSaturation(20);
            e.getPlayer().setHealth(20);
        }
    }

    @EventHandler
    public void onJoin(PlayerJoinEvent e) {
        e.getPlayer().teleport(new Location(Bukkit.getWorld("world"), 0.5, 4, 0.5));
        KitManager.getSpawnKit(e.getPlayer()); // 玩家进入 给玩家发放初始装备

        PlayerKitManager.loadPlayerKit(e.getPlayer());

        ScoreboardManager.initPlayerScoreboard(e.getPlayer());
        ScoreboardManager.initPlayerObjective(e.getPlayer());

        Bukkit.getScheduler().runTaskAsynchronously(Main.getInstance(), () -> {
            PlayerStatsImpl stats = TestFFACore.getStatsManager().loadPlayerStats(e.getPlayer());
            if (stats == null) return;
            ScoreboardManager.setLineSuffix(e.getPlayer(), 8, "§f" + stats.getKill());
            ScoreboardManager.setLineSuffix(e.getPlayer(), 7, "§f" + stats.getDeath());
            ScoreboardManager.setLineSuffix(e.getPlayer(), 6, "§f" + String.format("%.2f", (double) stats.getKill() / (double) stats.getDeath()));
        });
    }

    @EventHandler
    public void onQuit(PlayerQuitEvent e) {
        PlayerDiedEvent evt = new PlayerDiedEvent(e.getPlayer(), TestFFACore.getCombatManager().getCombatTarget(e.getPlayer()));
        Bukkit.getPluginManager().callEvent(evt);
        e.getPlayer().getActivePotionEffects().forEach(p -> e.getPlayer().removePotionEffect(p.getType()));
        PlayerKitManager.unloadPlayerKit(e.getPlayer());
        TestFFACore.getStatsManager().stats.remove(e.getPlayer());
        FakeGlassRunnable.fakeBlocks.remove(e.getPlayer());
    }

    @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
    public void onHealthChange(EntityDamageEvent e) {
        if (!(e.getEntity() instanceof Player)) return;
        Player player = (Player) e.getEntity();
        Bukkit.getOnlinePlayers().forEach(p -> {
            Scoreboard sb = p.getScoreboard();
            Objective objective = sb.getObjective("heatlh");
            if (objective == null) return;
            objective.getScore(player.getName()).setScore((int) (p.getHealth() - e.getFinalDamage()));
        });
    }

    @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
    public void onHealthChange(EntityRegainHealthEvent e) {
        if (!(e.getEntity() instanceof Player)) return;
        Player player = (Player) e.getEntity();
        Bukkit.getOnlinePlayers().forEach(p -> {
            Scoreboard sb = p.getScoreboard();
            Objective objective = sb.getObjective("heatlh");
            if (objective == null) return;
            objective.getScore(player.getName()).setScore((int) (p.getHealth() + e.getAmount()));
        });
    }

    @EventHandler
    public void onClick(PlayerInteractEvent e) { // 当玩家右键获得装备和编辑Kit的时候做出的处理
        if (e.getItem() == null || e.getItem().getItemMeta() == null || !e.getItem().getItemMeta().hasDisplayName())
            return;
        String name = e.getItem().getItemMeta().getDisplayName();
        if (name.equals("§b获得装备 §7(右键点击)")) {
            e.setCancelled(true);
            KitManager.getCombatKit(e.getPlayer());
        } else if (name.equals("§e编辑Kit §7(右键点击)")) {
            e.setCancelled(true);
            new KitEditGUI(e.getPlayer()).open();
        }
    }

    @EventHandler
    public void onMoveToSpawn(PlayerMoveEvent e) {
        if (TestFFACore.getCombatManager().getCombatTarget(e.getPlayer()) == null) return;
        Location location = e.getTo();
        if (e.getTo().getX() < 16 && e.getTo().getX() > -16 &&
                e.getTo().getZ() < 16 && e.getTo().getZ() > -16) {
            if (e.getFrom().getX() < 0) {
                if (e.getFrom().getZ() < 0) {
                    e.getPlayer().setVelocity(new Vector(-1, 0, -1));
                } else {
                    e.getPlayer().setVelocity(new Vector(-1, 0, 1));
                }
            } else {
                if (e.getFrom().getZ() < 0) {
                    e.getPlayer().setVelocity(new Vector(1, 0, -1));
                } else {
                    e.getPlayer().setVelocity(new Vector(1, 0, 1));
                }
            }
        }
    }

    @SuppressWarnings("ConstantConditions")
    @EventHandler
    public void onDied(PlayerDiedEvent e) {
        if (e.killer != null) {
            TestFFACore.getCombatManager().setCombatTime(e.player, 0);
            TestFFACore.getCombatManager().setCombatTarget(e.player, null);

            Player killerTarget = TestFFACore.getCombatManager().getCombatTarget(e.killer);

            Bukkit.getScheduler().runTaskAsynchronously(Main.getInstance(), () -> {
                PlayerStatsImpl stats = TestFFACore.getStatsManager().getOfflinePlayerStats(e.killer.getUniqueId());
                stats.setKill(stats.getKill() + 1);
                stats = TestFFACore.getStatsManager().getOfflinePlayerStats(e.player.getUniqueId());
                stats.setDeath(stats.getDeath() + 1);
            });

            KitManager.getCombatKit(e.killer);
            e.player.teleport(new Location(Bukkit.getWorld("world"), 0.5, 4, 0.5));
            KitManager.getSpawnKit(e.player);

            if (e.player.equals(killerTarget)) {
                TestFFACore.getCombatManager().setCombatTime(e.killer, 0);
                TestFFACore.getCombatManager().setCombatTarget(e.killer, null);
            }
        }
    }

    @EventHandler
    public void onEnderPearl(PlayerInteractEvent e) {
        if (e.getItem() != null && e.getItem().getType() == Material.ENDER_PEARL && (e.getAction() == Action.RIGHT_CLICK_AIR || e.getAction() == Action.RIGHT_CLICK_BLOCK)) {
            long cd = TestFFACore.getEnderPearlCoolDownManager().getPlayerEnderPearlCoolDown(e.getPlayer());
            if (cd != 0) {
                e.getPlayer().sendMessage(ColorUtils.parseColor("&7[&c×&7]&c您必须等待 " + String.format("%.2f", (double) cd / (double) 1000)) + " 才能再次使用末影珍珠");
                e.setCancelled(true);
            } else {
                TestFFACore.getEnderPearlCoolDownManager().setPlayerEnderPearlCoolDown(e.getPlayer(), 16000L);
            }
        }
    }

    @EventHandler
    public void onEnderPearlHit(PlayerTeleportEvent e) {
        if (e.getCause() == PlayerTeleportEvent.TeleportCause.ENDER_PEARL) {
            e.setCancelled(true);
            e.getPlayer().teleport(e.getTo());
        }
    }
}
